package cn.dongqihong.serialnum;

import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 每日序列编号生成类<br/>
 * 生成的格式是: 201209010000001 前面8位为当前的日期,后面7位为系统自增长类型的编号<br/>
 * 原理: <br/>
 * 1.获取当前日期格式化值;<br/>
 * 2.读取文件,上次编号的值+1最为当前此次编号的值 (新的一天会重新从1开始编号);<br/>
 * 
 * @author 董启宏
 */
public class EveryDaySerialNumGenerator {
	/**
	 * 序列号长度
	 */
	private int serialWidth = 7;
	/**
	 * 日期格式
	 */
	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
	/**
	 * 生成序列号所要用到的文件名
	 */
	private String serialFileName = "EveryDaySerialNumber.dat";

	private final static String FIELD_SEPARATOR = ":";

	/**
	 * 生成每日序号
	 * 
	 * @return 生成的序号
	 */
	public synchronized String generate() {
		Date date = new Date();
		int n = getAndUpdateNumber(date, 1);
		return dateFormat.format(date) + formatDate(n);
	}

	/**
	 * 格式化数字
	 * 
	 * @param num
	 *            要格式化的整数
	 * @return 格式化后的字符串
	 */
	private String formatDate(int num) {
		char[] chs = new char[serialWidth];
		for (int i = 0; i < serialWidth; i++) {
			chs[i] = '0';
		}
		DecimalFormat decimalFormat = new DecimalFormat(new String(chs));
		return decimalFormat.format(num);
	}

	/**
	 * 获取并更新数字
	 * 
	 * @param current
	 *            当前时间
	 * @param start
	 *            开始数字
	 * @return 新的数字
	 */
	private int getAndUpdateNumber(Date current, int start) {
		File file = new File(serialFileName);
		String date = dateFormat.format(current);
		int num = start;
		if (file.exists()) {
			List<String> list = FileUtil.readList(file);
			try {
				String[] data = list.get(0).split(FIELD_SEPARATOR);
				if (date.equals(data[0])) {
					num = Integer.parseInt(data[1]);
				}
			} catch (Exception IndexOutOfBoundsException) {
				num=1;
			}
		}
		FileUtil.rewrite(file, date + FIELD_SEPARATOR + (num + 1));
		return num;
	}

	/**
	 * 得到序列号的长度
	 * 
	 * @return 序列号的长度
	 */
	public int getSerialWidth() {
		return serialWidth;
	}

	/**
	 * 设置序列号的长度
	 * @param serialWidth
	 *            序列号的长度<br/>
	 *            注意：只能是1至9范围内的整数<br/>
	 */
	public void setSerialWidth(int serialWidth) {
		if (serialWidth < 1) {
			throw new IllegalArgumentException(
					"Parameter length must be great than 1!");
		}
		if (serialWidth > 9) {
			throw new IllegalArgumentException(
			"Parameter length must be less than 9!");
		}
		this.serialWidth = serialWidth;
	}

	/**
	 * 得到生成序列号所用到的文件名
	 * 
	 * @return 生成序列号所要用到的文件名
	 */
	public String getSerialFileName() {
		return serialFileName;
	}

	/**
	 * 设置生成序列号所要用到的文件名
	 * 
	 * @param serialFileName
	 *            生成序列号所要用到的文件名
	 */
	public void setSerialFileName(String serialFileName) {
		this.serialFileName = serialFileName;
	}
}
